package com.april.pattern.creational.prototype;

import org.junit.jupiter.api.Test;

import java.lang.reflect.Method;
import java.util.Date;

/**
 * @author April
 * @version V1.0.0
 * @date 2019/06/23 13:15
 * @description
 */
public class PrototypeTest {
    @Test
    public void prototypeShallowCopyTest() throws CloneNotSupportedException {
        Date date = new Date(1231232311L);
        SheepOne sheep1 = new SheepOne("少利", date);
        // 浅复制
        SheepOne sheep2 = (SheepOne) sheep1.clone();

        System.out.println(sheep1 + "     " + sheep1.getName() + " : " + sheep1.getBirthday());
        System.out.println(sheep2 + "     " + sheep2.getName() + " : " + sheep2.getBirthday());

        // 将原始的对象中的时间对象修改
        date.setTime(23432432423L);
        sheep1.setName("多利");

        System.out.println("===修改后===");
        System.out.println(sheep1 + "     " + sheep1.getName() + " : " + sheep1.getBirthday());
        System.out.println(sheep2 + "     " + sheep2.getName() + " : " + sheep2.getBirthday());
    }

    @Test
    public void prototypeDeepCopyTest() throws CloneNotSupportedException {
        Date date = new Date(1231232311L);
        SheepTwo sheep1 = new SheepTwo("少利", date);
        // 深复制
        SheepTwo sheep2 = (SheepTwo) sheep1.clone();

        System.out.println(sheep1 + "     " + sheep1.getName() + " : " + sheep1.getBirthday());
        System.out.println(sheep2 + "     " + sheep2.getName() + " : " + sheep2.getBirthday());

        date.setTime(23432432423L);
        sheep1.setName("多利");

        System.out.println("=====修改后=====");
        System.out.println(sheep1 + "     " + sheep1.getName() + " : " + sheep1.getBirthday());
        System.out.println(sheep2 + "     " + sheep2.getName() + " : " + sheep2.getBirthday());
    }

    /**
     * 如果单例实现了Cloneable接口然后重写了clone方法，这样就有可能破坏单例
     * 解决
     * 1. 不要重写cloneable接口
     * 2. 将实现的clone（）方法返回的是当前的实例
     * @throws Exception Exception
     */
    @Test
    public void toDestroySingletonByPrototypeTest() throws Exception {
        HungrySingleton hungrySingleton = HungrySingleton.getInstance();

        Method method = hungrySingleton.getClass().getDeclaredMethod("clone");
        method.setAccessible(true);
        HungrySingleton prototypeHungrySingleton = (HungrySingleton) method.invoke(hungrySingleton);

        System.out.println(hungrySingleton);
        System.out.println(prototypeHungrySingleton);
        System.out.println(hungrySingleton == prototypeHungrySingleton);
    }
}
